/**
 * DrowsinessAlgo class 
 * 
 * 
 * @created 2007-04-23
 * @author csamson
 * @author tlopez
 */

package sleeping;

import objects.*;
import kernel.*;
import java.lang.Math;
import java.util.*;
import java.awt.event.*;
import java.awt.*;


public class DrowsinessAlgo extends SleepingAlgo{

    private Vector< Vector<int[]> > _areaVect;

	

    public DrowsinessAlgo(){
	_areaVect = new Vector();
    }

    /**
     * @return the algorithm name
     */
    public String getName(){
	return "DrowsinessAlgo";
    }


    /**
     * Calculates the sleeping for a SensorNetwork
     *
     */
    public void calculateSleeping(){
	
	Vector<Sensor> sensorVect = _sn.getSensorVect();
	_areaVect = new Vector();
	//we wake up all the sensors if they are not already dead
	for(int i=0; i < sensorVect.size() ; i++){
		_areaVect.add(new Vector());
	    Sensor s=sensorVect.elementAt(i);
	    _sn.setSleeping(s,false);
	    setAreaVect(i);
	    
	}
	double max = 1;
	//We select a sensor that can go sleeping and
	//we continue as long as a sensor can be removed
	while(max>0){
	    max=-1;
	    int rang = 0;
	    for(int i=0; i<_areaVect.size();i++){
		if(sensorVect.elementAt(i).getBatteryLevel() > 0){
		    double drowFact = drowsinessFactor(sensorVect.elementAt(i), 
						       _areaVect.elementAt(i));
		    if(max < drowFact){
			max = drowFact;
			rang = i;
		    }
		}
	    }
	    //The one can go to sleep
	    if(max >0){
		_sn.setSleeping(sensorVect.elementAt(rang),true);
		_areaVect.elementAt(rang).clear();
	    }
	}
    }
	

    /**
     *
     *Set the area Vector
     *@param i one of the sensor of the sensorNetwork
     */
    public void setAreaVect(int i){
	    Sensor temp = _sn.getSensorVect().elementAt(i);
	    Vector<int[]> vect = new Vector();
		_areaVect.set(i,vect);
	    for(int j=temp.getCellMinX(); j<=temp.getCellMaxX();j++){
		for(int k=temp.getCellMinY();k<=temp.getCellMaxY();k++){
		    if(_sn.coverCell(temp,j,k)){
			int[] tab = {j,k};
			vect.add(tab);
		    }
		}
	    }
    }



    /**
     *
     *Calculate the drowsiness Factor of the current Sensor
     *
     *@param s the Sensor
     *@param coveredArea a Vector with the coordonate of the different cells that the sensor covers
     *@return the drowsinessFactor
     */
    public double drowsinessFactor(Sensor s, Vector<int[]> coveredArea){
	
	if(coveredArea.isEmpty()){
	    return -1;
	}

	double ener = s.getBatteryLevel();
	int kCover = _sn.getKCover();
	double sumArea = 0;

	for(int i =0; i<coveredArea.size();i++){
	    int[] coord = coveredArea.elementAt(i);
	    int cover = _sn.cellCover(coord[0], coord[1]);
	    if(cover > kCover){
		sumArea += 1 / (double)(cover - kCover);
	    }else{
		sumArea += -5;
	    }
	}
	double drowsi = (1/(ener*ener))*sumArea;
	return drowsi;
    }
	
	   
	    

}
